package game.core
{
	import engine.core.*;
	import engine.math.*;
	import flash.display.*;
	import game.*;
	import game.actor.*;
	import game.network.*;
	
	public class RxEntity
	{
		private var m_messageQueue:Vector.<RxMessage>;
		private var m_phase:int;
		private var m_type:int;
		private var m_name:String;
		private var m_id:int;
		private var m_updateIndex:int;
		private var m_typeIndex:int;
		private var m_sleep:Boolean;
		protected var m_debugColor:int;
		protected var m_debugSprite:Sprite;
		protected var m_debugParent:Sprite;
		private static var s_phaseNames:Vector.<String>;
		private static var s_numPhases:int;
		private static var s_typeNames:Vector.<String>;
		private static var s_numTypes:int;
		private static var s_updateArrays:Vector.<Vector.<RxEntity>>;
		private static var s_typeArrays:Vector.<Vector.<RxEntity>>;
		private static var s_enabledArray:Vector.<Boolean>;
		private static var s_nameArray:Object;
		private static var s_removedQueue:Vector.<RxEntity> = new Vector.<RxEntity>;
		private static var s_nextID:int;
		private static var s_messageListeners:Vector.<Vector.<RxEntity>>;
		public static const DEBUG_WIDTH:int = 1015;
		public static const DEBUG_HEIGHT:int = 550;
		public static const DEBUG_OFFSET_X:int = 0;
		public static const DEBUG_OFFSET_Z:int = 46;
		private static var s_debugScale:Number;
		private static var s_debugOffset:RxVector4 = new RxVector4();
		
		public function RxEntity(phase:int, type:int, name:String = null, debugColor:int = 8421504)
		{
			this.m_messageQueue = new Vector.<RxMessage>;
			this.m_debugColor = debugColor;
			this.m_debugSprite = null;
			this.m_id = s_nextID + 1;
			this.AddEntity(phase, type, name);
		}
		
		private function AddEntity(phase:int, type:int, name:String) : void
		{
			if (phase < 0 || phase >= s_numPhases)
			{
				RxLog.Error("Invalid update phase specified");
			}
			if (type < 0 || type >= s_numTypes)
			{
				RxLog.Error("Invalid entity type specified");
			}
			this.m_sleep = false;
			this.m_phase = phase;
			this.m_updateIndex = s_updateArrays[phase].length;
			s_updateArrays[phase].push(this);
			this.m_type = type;
			this.m_typeIndex = s_typeArrays[type].length;
			s_typeArrays[type].push(this);
			this.m_name = name;
			if (this.m_name)
			{
				if (s_nameArray[this.m_name])
				{
					RxLog.Error("Entity must have a unique name");
				}
				s_nameArray[this.m_name] = this;
			}
		}
		
		public static function Initialize(phaseNames:Vector.<String>, typeNames:Vector.<String>) : void
		{
			s_typeNames = typeNames;
			s_numTypes = typeNames.length;
			s_phaseNames = phaseNames;
			s_numPhases = phaseNames.length;
			
			s_updateArrays = new Vector.<Vector.<RxEntity>>(s_numPhases, true);
			var i:int = 0;
			while (i < s_numPhases)
			{
				
				s_updateArrays[i] = new Vector.<RxEntity>;
				i++;
			}
			
			s_typeArrays = new Vector.<Vector.<RxEntity>>(s_numTypes, true);
			var j:int = 0;
			while (j < s_numTypes)
			{
				
				s_typeArrays[j] = new Vector.<RxEntity>;
				j++;
			}
			
			s_enabledArray = new Vector.<Boolean>(s_numPhases, true);
			s_nameArray = new Object();
			s_nextID = 0;
			
			s_messageListeners = new Vector.<Vector.<RxEntity>>(RxMessage.eNumTypes);
			i = 0;
			while (i < RxMessage.eNumTypes)
			{
				
				s_messageListeners[i] = new Vector.<RxEntity>;
				i++;
			}
		}
		
		public static function EnablePhase(param1:int) : void
		{
			if (param1 < 0 || param1 >= s_numPhases)
			{
				RxLog.Error("Invalid entity phase specified");
				return;
			}
			s_enabledArray[param1] = true;
		}
		
		public static function FindByPhase(param1:String) : Vector.<RxEntity>
		{
			var _loc_3:int = 0;
			var _loc_2:Vector.<RxEntity> = null;
			_loc_3 = 0;
			while (_loc_3 < s_phaseNames.length)
			{
				
				if (s_phaseNames[_loc_3] == param1)
				{
					_loc_2 = s_updateArrays[_loc_3];
					break;
				}
				_loc_3++;
			}
			return _loc_2;
		}
		
		public static function UpdateAll(param1:Number) : void
		{
			var _loc_2:Vector.<RxEntity> = null;
			var _loc_3:int = 0;
			var _loc_4:RxEntity = null;
			var _loc_5:RxEntity = null;
			var _loc_6:RxMessage = null;
			_loc_3 = 0;
			for each (_loc_2 in s_updateArrays)
			{
				
				if (s_enabledArray[_loc_3++] == true)
				{
					for each (_loc_4 in _loc_2)
					{
						
						if (_loc_4.IsAsleep() == false)
						{
							_loc_4.Update(param1);
						}
					}
				}
			}
			_loc_3 = 0;
			for each (_loc_2 in s_updateArrays)
			{
				
				if (s_enabledArray[_loc_3++] == true)
				{
					for each (_loc_4 in _loc_2)
					{
						
						if (_loc_4.IsAsleep() == false)
						{
							_loc_4.PostUpdate(param1);
						}
					}
				}
			}
			for each (_loc_2 in s_updateArrays)
			{
				
				for each (_loc_4 in _loc_2)
				{
					
					for each (_loc_6 in _loc_4.m_messageQueue)
					{
						
						_loc_4.Message(_loc_6);
					}
					_loc_4.m_messageQueue.length = 0;
				}
			}
			for each (_loc_5 in s_removedQueue)
			{
				
				_loc_5.RemoveEntity();
			}
			s_removedQueue.length = 0;
		}
		
		public static function UpdateActorAttachments(param1:Number) : void
		{
			
			var _loc_2:Vector.<RxEntity> = null;
			var _loc_3:RxEntity = null;
			var _loc_4:RxActor = null;
			if (s_enabledArray[RxEntityPhase.ENTITY_PHASE_HERO] == true)
			{
				_loc_2 = s_updateArrays[RxEntityPhase.ENTITY_PHASE_HERO];
				for each (_loc_3 in _loc_2)
				{
					
					if (_loc_3.IsAsleep() == false)
					{
						_loc_4 = _loc_3 as RxActor;
						_loc_4.UpdateAttachments(param1);
					}
				}
			}
			if (s_enabledArray[RxEntityPhase.ENTITY_PHASE_NPC] == true)
			{
				_loc_2 = s_updateArrays[RxEntityPhase.ENTITY_PHASE_NPC];
				for each (_loc_3 in _loc_2)
				{
					
					if (_loc_3.IsAsleep() == false)
					{
						_loc_4 = _loc_3 as RxActor;
						_loc_4.UpdateAttachments(param1);
					}
				}
			}
			
		}
		
		public static function DebugDisplay(param1:Sprite, param2:Number, param3:Number) : void
		{
			/*
			var _loc_5:Vector.<RxEntity> = null;
			var _loc_6:RxEntity = null;
			var _loc_4:Boolean = false;
			if (false || RxTransactionServer.instance.hasQAPermission())
			{
				if (RxKeyboard.isPressed(RxKeyboard.KEY_N))
				{
					RxClientVars.SetInt("showNodeDebug", RxClientVars.GetInt("showNodeDebug") ^ 1);
				}
			}
			for each (_loc_5 in s_updateArrays)
			{
				
				for each (_loc_6 in _loc_5)
				{
					
					if (_loc_6.DebugShouldRender())
					{
						_loc_6.DebugRender(param1, RxClientVars.GetInt("showNodeDebug"));
					}
				}
			}
			return;*/
		}
		
		public function IsAsleep() : Boolean
		{
			return this.m_sleep;
		}
		
		protected function Update(param1:Number) : void
		{
			RxLog.Warning("Call to virtual function RxEntity.Update()");
		}
		
		protected function PostUpdate(param1:Number) : void
		{
			RxLog.Warning("Call to virtual function RxEntity.PostUpdate()");
		}
		
		protected function Message(param1:RxMessage) : void
		{
			RxLog.Warning("Call to virtual function RxEntity.Message()");
		}
		
		protected function Delete() : void
		{
			RxLog.Warning("Call to virtual function RxEntity.Delete()");
		}
		
		private function RemoveEntity() : void
		{
			this.Delete();
			var _loc_1:* = s_updateArrays[this.m_phase].pop();
			if (_loc_1 != this)
			{
				s_updateArrays[this.m_phase][this.m_updateIndex] = _loc_1;
				_loc_1.m_updateIndex = this.m_updateIndex;
			}
			_loc_1 = s_typeArrays[this.m_type].pop();
			if (_loc_1 != this)
			{
				s_typeArrays[this.m_type][this.m_typeIndex] = _loc_1;
				_loc_1.m_typeIndex = this.m_typeIndex;
			}
			if (this.m_name)
			{
				delete s_nameArray[this.m_name];
			}
			if (this.m_debugSprite != null)
			{
				this.m_debugParent.removeChild(this.m_debugSprite);
			}
		}
		
		public static function FindByType(param1:int) : Vector.<RxEntity>
		{
			if (param1 < 0 || param1 >= s_numTypes)
			{
				RxLog.Error("Invalid entity type specified");
				return null;
			}
			return s_typeArrays[param1];
		}
	}
}